package com.zilue.payment.gateway.manage;

import com.alibaba.dubbo.rpc.RpcException;
import com.alibaba.fastjson.JSON;
import com.zilue.balance.domain.BaseOrderInfo;
import com.zilue.balance.returnresult.Result;
import com.zilue.payment.gateway.common.FeeChannelEnums;
import com.zilue.payment.gateway.common.RefundStatusEnums;
import com.zilue.payment.gateway.domain.CorpDO;
import com.zilue.payment.gateway.domain.PayOrderDO;
import com.zilue.payment.gateway.domain.RefundLogDO;
import com.zilue.payment.gateway.exception.BizManagerException;
import com.zilue.payment.gateway.mapper.RefundLogMapper;
import com.zilue.payment.gateway.method.remote.BalancePayRemote;
import com.zilue.payment.gateway.paramter.order.CancleParameter;
import com.zilue.payment.gateway.reurndata.PublicReturn;
import com.zilue.payment.gateway.reurndata.enums.BusinessStatusEnum;
import com.zilue.payment.gateway.reurndata.enums.RequestStatusEnum;
import com.zilue.payment.gateway.reurndata.order.CancleReturn;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * Created by zilue on 2017/4/20.
 */
@Service
public class CancleManager extends BaseManager {
    private static final Logger logger = Logger.getLogger(CancleManager.class);
    private static final String ACTION_CLOSE = "close";
    private static final String ACTION_REFUND = "refund";
    @Autowired
    private BalancePayRemote BalancePayRemote;
    @Autowired
    private RefundLogMapper refundLogMapper;

    @Transactional
    public CancleReturn cancleOrder(CorpDO corpDO, CancleParameter cancleParameter) throws BizManagerException {
        CancleReturn cancleReturn = new CancleReturn(RequestStatusEnum.RequestSuccess);
        //1.查询原订单
        PayOrderDO payOrder = queryByOrderNoOutTradeNo(cancleParameter.getOrder_no(), cancleParameter.getOut_trade_no(), cancleParameter.getOut_pay_no(), corpDO.getParentCorpId(), corpDO.getCorpId());
        if (payOrder == null) {
            cancleReturn.setBusinessStatus(BusinessStatusEnum.OrderNotExist);
            return cancleReturn;
        }
        //2.检查原订单状态
        if (PayOrderDO.STATUS_WAIT_FOR_PAY.equals(payOrder.getStatus())) {//关闭订单
            boolean ok = updatePayOrderStatus(payOrder.getId(), PayOrderDO.STATUS_WAIT_FOR_PAY, PayOrderDO.STATUS_CANCLE);
            if (!ok) {
                throw new BizManagerException(BusinessStatusEnum.OrderStatusIllegal);
            }
            cancleReturn.setOut_trade_no(payOrder.getOutTradeNo());
            cancleReturn.setOut_pay_no(payOrder.getOutPayNo());
            cancleReturn.setOrder_no(payOrder.getOrderNo());
            cancleReturn.setAction(ACTION_CLOSE);
            cancleReturn.setBusinessStatus(BusinessStatusEnum.OrderCancleSuccess);
            return cancleReturn;
        } else if (PayOrderDO.STATUS_CANCLE.equals(payOrder.getStatus())) {
            cancleReturn.setOut_trade_no(payOrder.getOutTradeNo());
            cancleReturn.setOut_pay_no(payOrder.getOutPayNo());
            cancleReturn.setOrder_no(payOrder.getOrderNo());
            cancleReturn.setAction(ACTION_CLOSE);
            cancleReturn.setBusinessStatus(BusinessStatusEnum.OrderCancleSuccess);
            return cancleReturn;
        } else if (PayOrderDO.STATUS_CLOSED.equals(payOrder.getStatus())) {
            cancleReturn.setOut_trade_no(payOrder.getOutTradeNo());
            cancleReturn.setOut_pay_no(payOrder.getOutPayNo());
            cancleReturn.setOrder_no(payOrder.getOrderNo());
            cancleReturn.setAction(ACTION_REFUND);
            cancleReturn.setBusinessStatus(BusinessStatusEnum.OrderCancleSuccess);
            return cancleReturn;
        } else if (PayOrderDO.STATUS_SUCCESS.equals(payOrder.getStatus())) {//撤单退费
            if (payOrder.getRefundFee() != null && payOrder.getRefundFee().longValue() != 0L) {
                throw new BizManagerException(BusinessStatusEnum.OrderCancleFailedOrderRefund);
            }
            boolean ok = updatePayOrderStatus(payOrder.getId(), PayOrderDO.STATUS_SUCCESS, PayOrderDO.STATUS_CLOSED);
            if (!ok) {
                throw new BizManagerException(BusinessStatusEnum.OrderStatusIllegal);
            }
            ok = updatePayOrderRefundFee(payOrder.getId(), payOrder.getRefundFee(), payOrder.getTotalAmount());
            if (!ok) {
                throw new BizManagerException(BusinessStatusEnum.OrderStatusIllegal);
            }
            Result<BaseOrderInfo> flushes;
            try {
                flushes = BalancePayRemote.flushes(payOrder.getOutPayNo(), payOrder.getCorpId(), 1, cancleParameter.getTerminal_id(), cancleParameter.getOperator_id());
                if (!flushes.isSuccess()) {
                    logger.info("撤单失败，请求参数：" + JSON.toJSONString(cancleParameter) + " 原交易订单：" + JSON.toJSONString(payOrder));
                    throw new BizManagerException(BusinessStatusEnum.OrderCancleFailed, flushes.getMsg());
                }
                RefundLogDO refundLogDO = insertRefundLog(payOrder, cancleParameter);
                if (refundLogDO == null) {
                    logger.error("撤单插入退费记录失败！！！");
                }
            } catch (RpcException e) {
                logger.error("严重！！调用虚拟结算撤单异常,Dubbo异常！！！ 撤单请求参数：" + JSON.toJSONString(cancleParameter) + " 原交易订单：" + JSON.toJSONString(payOrder), e);
                throw new BizManagerException(BusinessStatusEnum.Busyness);

            }
            cancleReturn.setOut_trade_no(payOrder.getOutTradeNo());
            cancleReturn.setOut_pay_no(payOrder.getOutPayNo());
            cancleReturn.setOrder_no(payOrder.getOrderNo());
            cancleReturn.setAction(ACTION_REFUND);
            cancleReturn.setBusinessStatus(BusinessStatusEnum.OrderCancleSuccess);
            return cancleReturn;
        } else if (PayOrderDO.STATUS_REFUND.equals(payOrder.getStatus())) {
            cancleReturn.setBusinessStatus(BusinessStatusEnum.OrderCancleFailedOrderRefund);
            return cancleReturn;
        }
        cancleReturn.setBusinessStatus(BusinessStatusEnum.OrderStatusIllegal);
        return cancleReturn;
    }

    public RefundLogDO insertRefundLog(PayOrderDO payOrder, CancleParameter cancleParameter) {

        RefundLogDO refundLogDO = RefundLogDO.builder().outRefundNo(payOrder.getOutPayNo()).outTradeNo(payOrder.getOutTradeNo())
                .reason("商户撤单").fee(payOrder.getTotalAmount()).terminalId(cancleParameter.getTerminal_id())
                .operatorId(cancleParameter.getOperator_id()).feeChannel(FeeChannelEnums.BALANCE.getCode())
                .corpId(payOrder.getSubCorpId()).status(RefundStatusEnums.REFUND_SUCCUSS.getCode()).build();
//        refundLogDO.setOptType(OptTypeEnums.PAYMENT.getCode());//TODO 这里不应该写死
//        refundLogDO.setSource(cancleParameter.getStore_id());
        long row = refundLogMapper.insert(refundLogDO);
        if (row > 0)
            return refundLogDO;
        else
            return null;
    }
}
